<?php

namespace app\common\library;

use esign\comm\EsignHttpHelper;
use esign\comm\EsignLogHelper;
use esign\comm\EsignUtilHelper;
use esign\emun\HttpEmun;
use think\Env;
use function Composer\Autoload\includeFile;

/**
 * create by PhpStorm 2025/4/27 19:18
 * sdwxorg app\common\library@Esign
 * 行止之行 <xingzhi8711@gmail.com>
 *
 */
class Esign
{
    protected $config = [
        'eSignAppId'=>"5111629205", //app id
        'eSignAppSecret'=>'95a1b9be91630ec916ee9699ccbf388e', // app key
//        'eSignHost'=>'https://smlopenapi.esign.cn', //模拟环境
        'url'=>'https://openapi.esign.cn' //正式环境
    ];
    protected $fileName;
    protected $option=[];
    public function __construct($option=[])
    {
        $this->config['eSignAppId'] = Env::get('esign.appid',"5111629205");
        $this->config['eSignAppSecret'] = Env::get('esign.secret',"5111629205");
        if(!$option){
            setLog(__METHOD__,"**********初始化失败**********");
            return false;
        }
        $this->option=$option;
        $this->fileName=$this->option['name']."_".$this->option['phone']."_".$this->option['doc_name'].".pdf";
    }
    function createByFile(){
        setlog(__METHOD__,"**********基于文件发起签署调用开始**********");
        $config=$this->config;
        $mobile=$this->option['phone'];
        $apiaddr="/v3/sign-flow/create-by-file";
        $requestType = HttpEmun::POST;
        //上传文件，获取文件id
        $filePath=$this->option['doc_file'];
//        $filePath="/Users/cmn/Sites/V3 Demo/SaaSAPI_V3_Demo_PHP/pdf/test1.pdf";
        $contentMd5=$this->contentMd5($filePath);
        $fileId=$this->fileUploadUrl($filePath,$contentMd5);

        $data = [
            "docs" =>[
                [
                    "fileId" =>$fileId,
                    "fileName" =>$this->fileName
                ]
            ],
            "signFlowConfig" => [
                "signFlowTitle" =>$this->option['doc_name'],
                "autoFinish"=>true
            ],
            "signers" =>[
                [
                    "psnSignerInfo" => [
                        "psnAccount" => $mobile
                    ],
                    "signFields" =>[
                        [
                            "fileId" =>$fileId,
                            "normalSignFieldConfig" => [
                                "autoSign" =>false,
                                "signFieldStyle" =>1,
                                "signFieldPosition" => [
                                    "positionPage" =>"1",
                                    "positionX" =>100,
                                    "positionY" =>200
                                ]
                            ]
                        ]
                    ],
                    "signerType" =>0
                ],
                [
                    "orgSignerInfo" => [
                        "orgId" => $this->option['org_id']   //平台方机构oid
                    ],
                    "signFields" =>[
                        [
                            "fileId" =>$fileId,
                            "normalSignFieldConfig" => [
                                "autoSign" =>true,
                                "signFieldStyle" =>1,
                                "signFieldPosition" => [
                                    "positionPage" =>"1",
                                    "positionX" =>300,
                                    "positionY" =>200
                                ]
                            ]
                        ]
                    ],
                    "signerType" =>1
                ]
            ]
        ];
        $paramStr = json_encode($data);

        $signAndBuildSignAndJsonHeader = EsignHttpHelper::signAndBuildSignAndJsonHeader($config['eSignAppId'], $config['eSignAppSecret'], $paramStr, $requestType, $apiaddr);

        setlog(__METHOD__,$signAndBuildSignAndJsonHeader);
        $response = EsignHttpHelper::doCommHttp($config['eSignHost'], $apiaddr, $requestType, $signAndBuildSignAndJsonHeader, $paramStr);
        setlog(__METHOD__,$response->getStatus());
        setlog(__METHOD__,$response->getBody());

        $flowId = false;
        if($response->getStatus() == 200){
            $result = json_decode($response->getBody());
            if($result->code==0){
                $flowId = $result->data->signFlowId;
                setlog(__METHOD__,"基于文件发起签署接口调用成功，flowId: ".$flowId);
            }else{
                setlog(__METHOD__,"基于文件发起签署接口调用失败，错误信息: ".$result->message);
            }
        }else{
            setlog(__METHOD__,"基于文件发起签署接口调用失败，HTTP错误码".$response->getStatus());
        }
        setlog(__METHOD__,"**********基于文件发起签署调用结束**********");
        $signUrl=$this->getSignUrl($flowId);
        return ['follow_id'=>$flowId,'sign_url'=>$signUrl];
    }


    function getSignUrl($flowId){
        setlog(__METHOD__,"**********获取合同文件签署链接开始**********");
        global $config ,$mobile;

        $apiaddr="/v3/sign-flow/%s/sign-url";
        $apiaddr = sprintf($apiaddr,$flowId);
        $requestType = HttpEmun::POST;
        $data = [
            "clientType" =>"ALL",
            "needLogin" =>false,
            "operator" => [
                "psnAccount" =>$mobile
            ],
            "urlType" =>2
        ];
        $paramStr = json_encode($data);

        $signAndBuildSignAndJsonHeader = EsignHttpHelper::signAndBuildSignAndJsonHeader($config['eSignAppId'], $config['eSignAppSecret'], $paramStr, $requestType, $apiaddr);

        setlog(__METHOD__,$signAndBuildSignAndJsonHeader);
        $response = EsignHttpHelper::doCommHttp($config['eSignHost'], $apiaddr, $requestType, $signAndBuildSignAndJsonHeader, $paramStr);
        setlog(__METHOD__,$response->getStatus());
        setlog(__METHOD__,$response->getBody());
        $url= null;
        if($response->getStatus() == 200){
            $url =  json_decode($response->getBody())->data->shortUrl;
            setlog(__METHOD__,"获取合同文件签署链接调用成功，url: ".$url);
        }else{
            setlog(__METHOD__,"获取合同文件签署链接接口调用失败，HTTP错误码".$response->getStatus());
        }
        setlog(__METHOD__,"**********获取合同文件签署链接调用结束**********");
        return $url;
    }

    /**
     * 下载已签署文件及附属材料
     */
    function downloadFile($flowId){
        global $config ;

        setlog(__METHOD__,"**********下载已签署文件及附属材料开始**********");
        $apiaddr="/v3/sign-flow/%s/file-download-url";
        $apiaddr = sprintf($apiaddr,$flowId);
        $requestType = HttpEmun::GET;
        $paramStr = null;
        $signAndBuildSignAndJsonHeader = EsignHttpHelper::signAndBuildSignAndJsonHeader($config['eSignAppId'], $config['eSignAppSecret'], $paramStr, $requestType, $apiaddr);

        setlog(__METHOD__,$signAndBuildSignAndJsonHeader);
        $response = EsignHttpHelper::doCommHttp($config['eSignHost'], $apiaddr, $requestType, $signAndBuildSignAndJsonHeader, $paramStr);
        setlog(__METHOD__,$response->getStatus());
        setlog(__METHOD__,$response->getBody());
        if($response->getStatus() == 200){
            setlog(__METHOD__,"下载已签署文件及附属材料调用成功: ".$response->getBody());
        }else{
            setlog(__METHOD__,"下载已签署文件及附属材料调用失败，HTTP错误码".$response->getStatus());
        }
        setlog(__METHOD__,"**********下载已签署文件及附属材料调用结束**********");
    }

    public function contentMd5($filePath){
        if(!file_exists($filePath)){
            setlog(__METHOD__,$filePath."文件不存在");exit;
        }
        return EsignUtilHelper::getContentBase64Md5($filePath);
    }

    /**
     * @param $filePath
     * @param $contentMd5
     * @return mixed
     */
    public function fileUploadUrl($filePath,$contentMd5){
        global $config ;
        $apiaddr="/v3/files/file-upload-url";
        $requestType = HttpEmun::POST;
        $data=[
            "contentMd5" =>$contentMd5,
            "contentType" =>"application/pdf",
            "convertToPDF" =>false,
            "fileName" =>$this->fileName,
            "fileSize" =>filesize($filePath)
        ];
        $paramStr = json_encode($data);
        //生成签名验签+json体的header

        $signAndBuildSignAndJsonHeader = EsignHttpHelper::signAndBuildSignAndJsonHeader($config['eSignAppId'], $config['eSignAppSecret'], $paramStr, $requestType, $apiaddr);
        //获取文件上传地址
        setlog(__METHOD__,$signAndBuildSignAndJsonHeader);
        $response = EsignHttpHelper::doCommHttp($config['eSignHost'], $apiaddr, $requestType, $signAndBuildSignAndJsonHeader, $paramStr);
        setlog(__METHOD__,$response->getStatus());
        setlog(__METHOD__,$response->getBody());
        $fileUploadUrl=json_decode($response->getBody())->data->fileUploadUrl;
        $fileId=json_decode($response->getBody())->data->fileId;
        //文件流put上传
        $response=EsignHttpHelper::upLoadFileHttp($fileUploadUrl,$filePath,"application/pdf");
        setlog(__METHOD__,$response->getStatus());
        setlog(__METHOD__,$response->getBody());
        return $fileId;
    }

    /**
     * @param $filePath
     * @param $contentMd5
     * @return mixed
     */
    public function fileUploadToHtmlUrl($filePath,$contentMd5){
        global $config ;
        $apiaddr="/v3/files/file-upload-url";
        $requestType = HttpEmun::POST;
        $data=[
            "contentMd5" =>$contentMd5,
            "contentType" =>"application/octet-stream",
            "fileName" =>"房屋租赁协议.docx",
            "fileSize" =>filesize($filePath),
            "convertToHTML"=>true
        ];
        $paramStr = json_encode($data);
        //生成签名验签+json体的header

        $signAndBuildSignAndJsonHeader = EsignHttpHelper::signAndBuildSignAndJsonHeader($config['eSignAppId'], $config['eSignAppSecret'], $paramStr, $requestType, $apiaddr);
        //获取文件上传地址
        setlog(__METHOD__,$signAndBuildSignAndJsonHeader);
        $response = EsignHttpHelper::doCommHttp($config['eSignHost'], $apiaddr, $requestType, $signAndBuildSignAndJsonHeader, $paramStr);
        setlog(__METHOD__,$response->getStatus());
        setlog(__METHOD__,$response->getBody());
        $fileUploadUrl=json_decode($response->getBody())->data->fileUploadUrl;
        $fileId=json_decode($response->getBody())->data->fileId;
        //文件流put上传
        $response=EsignHttpHelper::upLoadFileHttp($fileUploadUrl,$filePath,"application/octet-stream");
        setlog(__METHOD__,$response->getStatus());
        setlog(__METHOD__,$response->getBody());
        return $fileId;
    }
}